
/// @author: slc
/// 定义选择框接口
abstract class ISelectBox<T> {
  T? get boxData; // 获取选择框数据
  set boxData(T? data); // 设置选择框数据

  int? get boxSelectIndex; // 获取选择索引
  set boxSelectIndex(int? index); // 设置选择索引

  /// 获取选择索引，如果为空则返回-1
  int getBoxSelectIndex() {
    return boxSelectIndex ?? -1;
  }

  bool? get boxChecked; // 获取选中状态
  set boxChecked(bool? checked); // 设置选中状态

  /// 获取选中状态，如果为空则返回false
  bool isBoxChecked() {
    return boxChecked ?? false;
  }

  set boxChildren(List<T>? children); // 设置子元素列表
  List<T>? get boxChildren; // 获取子元素列表
}

/// 将 SelectBox 改为可混入的 Mixin
mixin SelectBoxMixin<T> implements ISelectBox<T> {
  // 使用 Map 存储选择框状态
  final Map<String, dynamic> _boxMap = {};

  /// 初始化方法（由混入类调用）
  void initSelectBox({int index = -1, bool checked = false}) {
    _boxMap.addAll({
      'selectIndex': index,
      'checked': checked,
    });
  }

  /// 接口实现

  /// 混入时，data就是本身
  @override
  T? get boxData => this as T;

  @override
  set boxData(T? value) {
    // 此处什么都不用做
  }

  /// 此处可以是空是为了防止json序列化报错
  @override
  int? get boxSelectIndex => _boxMap['selectIndex'] as int?;

  @override
  set boxSelectIndex(int? value) => _boxMap['selectIndex'] = value;

  @override
  int getBoxSelectIndex() {
    return boxSelectIndex ?? -1;
  }

  @override
  bool? get boxChecked => _boxMap['checked'] as bool?;

  @override
  set boxChecked(bool? value) => _boxMap['checked'] = value;

  @override
  bool isBoxChecked() {
    return boxChecked ?? false;
  }

  @override
  set boxChildren(List<T>? value) {
    // 此处什么都不用做
  }

  @override
  List<T>? get boxChildren => null;
}

/// 定义一个具体的类
class SelectBox<T> with SelectBoxMixin<T> {
  SelectBox(T data, [int index = -1, bool checked = false]) {
    this.boxData = data;
    this.boxSelectIndex = index;
    this.boxChecked = checked;
  }

  SelectBox.fromData(T data) : this(data, -1, false);

  SelectBox.withIndex(T data, int index) : this(data, index, false);

  SelectBox.withChecked(T data, bool checked) : this(data, -1, checked);

  @override
  T get boxData => _boxMap['data'] as T;

  @override
  set boxData(T? value) => _boxMap['data'] = value;

  set boxChildren(List<T>? children) => _boxMap['children'] = children;
}

typedef Closure<E> = void Function(int index, E item); // 闭包类型定义
typedef Predicate<T, S> = bool Function(T src, S beCompared); // 谓词类型定义

class SelectUtils {
  /// 全选/全不选
  static selectAll<T>(List<ISelectBox<T>>? dataList, bool isSelected,
      {bool penetrate = false}) {
    if (dataList == null) {
      return;
    }
    for (var item in dataList) {
      item.boxChecked = isSelected;
      if (item.boxChildren != null && penetrate) {
        selectAll(item.boxChildren as List<ISelectBox<T>>, isSelected,
            penetrate: penetrate);
      }
    }
  }

  /// 获取选择的列表
  static List<S>? getSelect<T, S>(List<ISelectBox<T>>? dataList,
      {List<S>? collection,
      S convert(ISelectBox<T> event)?,
      bool penetrate = false}) {
    if (dataList == null) {
      return null;
    }

    collection ??= List.empty(growable: true);
    convert ??= (src) {
      return src as S;
    };
    for (var item in dataList) {
      if (item.isBoxChecked()) {
        collection.add(convert(item));
      }
      if (item.boxChildren != null && penetrate) {
        getSelect(item.boxChildren as List<ISelectBox<T>>,
            collection: collection, convert: convert, penetrate: penetrate);
      }
    }
    return collection;
  }

  /// 获取单个选择框的选中状态
  static bool? getSelectFromSingle<T>(ISelectBox<T> targetBox,
      {bool linkage = true}) {
    if (linkage) {
      return _getSelectListWithLinkage([targetBox]);
    } else {
      return targetBox.isBoxChecked();
    }
  }

  //获取三态的状态
  //return true：选中，false：未选中，null：子类有选择
  static bool? getSelectWithLinkage<T>(ISelectBox<T> targetBox) {
    return _getSelectListWithLinkage([targetBox]);
  }

  //如果T和S的类型不相同，请务必配置convert
  //获取选择的列表，父子联动形势
  //return true：选中，false：未选中，null：子类有选择
  static List<S>? getSelectListWithLinkage<T, S>(List<ISelectBox<T>>? dataList,
      {List<S>? collection, S convert(ISelectBox<T> event)?}) {
    collection ??= List.empty(growable: true);
    if (dataList == null || dataList.isEmpty) {
      return collection;
    }
    _getSelectListWithLinkage(dataList, collection: collection, convert: convert);
    return collection;
  }

  /// 内部方法：处理父子联动的选择逻辑
  static bool? _getSelectListWithLinkage<T, S>(List<ISelectBox<T>> dataList,
      {List<S>? collection, S convert(ISelectBox<T> event)?}) {
    if (dataList.isEmpty) {
      throw new Exception("dataList的不能为Empty！");
    }
    if (collection != null) {
      //此处得出collection不为空时convert也必定不为空
      convert ??= (src) {
        return src as S;
      };
    }
    //子节点联动结果
    int dataListCount = dataList.length;
    int childCheckedCount = 0;
    int childUnCheckCount = 0;
    for (var item in dataList) {
      List<ISelectBox<T>>? boxChildren =
          item.boxChildren as List<ISelectBox<T>>?;
      //如果没有子节点，节点本身是啥样就是啥样
      if (boxChildren == null || boxChildren.isEmpty) {
        if (item.isBoxChecked()) {
          childCheckedCount++;
          //收集
          collection?.add(convert!(item));
        }else{
          childUnCheckCount++;
        }
      } else {
        bool? childSelectStatus = _getSelectListWithLinkage(boxChildren,
            collection: collection, convert: convert);
        if (childSelectStatus == null) {
          //收集：为空也要收集
          collection?.add(convert!(item));
        } else if (childSelectStatus) {
          //收集：为true收集
          collection?.add(convert!(item));
          childCheckedCount++;
        } else {
          childUnCheckCount++;
        }
      }
    }
    if (dataListCount == childUnCheckCount) {
      return false;
    }
    if (dataListCount == childCheckedCount) {
      return true;
    }
    return null;
  }

  /// 将普通列表转换为选择对象列表
  static List<ISelectBox<T>> toSelect<T, S>(List<T>? dataList,
      {Iterable<S>? selectList,
      Predicate<T?, S?>? predicate,
      bool maintain = false,
      bool penetrate = false}) {
    List<ISelectBox<T>> selectBoxList = List.empty(growable: true);
    if (dataList == null) {
      return selectBoxList;
    }
    SelectUtils.fillSelect(selectBoxList, selectList,
        predicate: predicate, maintain: maintain, penetrate: penetrate);
    return selectBoxList;
  }

  /// 填充选择状态
  static void fillSelect<T, S>(
      List<ISelectBox<T>>? dataList, Iterable<S>? selectList,
      {Predicate<T?, S?>? predicate,
      bool maintain = false,
      bool penetrate = false}) {
    //数据为空则不进行
    if (dataList == null) {
      return;
    }
    //配置predicate！=null;
    predicate ??= (src, beCompared) {
      return src == beCompared;
    };
    for (var item in dataList) {
      //配置是否保持
      if (!maintain) {
        item.boxChecked = false;
      }
      //根据selectList填充是否选择
      if (selectList != null) {
        for (final selectedItem in selectList) {
          if (predicate(item.boxData, selectedItem)) {
            item.boxChecked = true;
            break;
          }
        }
      }
      ;
      //填充子节点
      if (item.boxChildren != null && penetrate) {
        SelectUtils.fillSelect(
            item.boxChildren as List<ISelectBox<T>>, selectList,
            predicate: predicate, maintain: maintain, penetrate: penetrate);
      }
    }
  }
}
